home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
338_01
/
bc.c
< prev
next >
Wrap
Text File
|
1988-02-23
|
17KB
|
783 lines
/* bc.c, code building function of as68 assembler
*
* (C) Copyright 1982 Steve Passe
* All Rights Reserved
*
* version 1.00
* created 10/21/82
*
* version 1.01
*
* 8/30/83 ver. 1.01 modified for Aztec ver. 1.05g smp
* 10/12/87 split into root, pass1 and pass2 parts for overlay on pdp-11
*/
/* begincode */
/* includes */
#include <stdio.h>
#include "as68.h"
/* externals */
extern char pass; /* present pass number, 1 or 2 */
extern unsigned line_count; /* line number of source file */
extern long loc_counter; /* address to assemble obj code */
extern int loc_plus; /* increment to loc counter */
extern FLAG abs_long; /* default to absolute long add.*/
extern FLAG rorg; /* in pc relative mode */
extern char label[32]; /* buffer for label from preparse */
extern char instr[33]; /* buffer for mnem, psdo or macro */
extern struct _mtable mtable[]; /* mnemonic lookup table */
extern struct _mvalue mvalue[]; /* mnemonic code table */
extern struct _oprnd op1, op2; /* structs to hold operand val */
extern char code[]; /* code array */
match(mt)
register struct _mtable *mt;
{
register int index; /* index to mvalue */
int type1 = _none, type2 = _none; /* operand types */
op_clear(&op1);
op_clear(&op2);
if (mt->_nops >= 1 && (type1 = op_eval(&op1)) < 0) { /* legal type found? */
err_out(BAD_OP1); /* first op bad */
}
if (mt->_nops == 2 && (type2 = op_eval(&op2)) < 0) { /* second op? */
err_out(BAD_OP2); /* no good */
}
if (type1 < 0 || type2 < 0) {
return ERROR; /* use NULL opcode */
}
if ((index = type_search(mt, type1, type2)) <=0) {
switch (index) {
case ILGL_OP1:
err_out(ILGL_OP1); /* no good */
return ERROR;
case ILGL_OP2:
err_out(ILGL_OP2); /* no good */
return ERROR;
default:
return ERROR;
}
}
return index;
}
type_search(mt, type1, type2)
struct _mtable *mt;
int type1;
int type2;
{
register int x, y; /* count and index */
register int t1, t2; /* temp for array value */
for (x = mt->_mvc, y = mt->_mvi; x; --x, ++y) { /* search */
/* find op1 match... */
if (((t1 = mvalue[y]._optyp1) == type1) /* if exact match */
|| ((!(t1 & ~0xf0)) && (t1 & type1))) { /* or classtyp and match */
/* search for second match */
for ( ; (mvalue[y]._optyp1 == t1) && x; --x, ++y) {
if (((t2 = mvalue[y]._optyp2) == type2) /* 2nd matches */
|| ((!(t2 & ~0xf0)) && (t2 & type2))) { /* or typ & match */
return y; /* found a match */
}
}
return ILGL_OP2;
}
}
return ILGL_OP1;
}
/* mask 3 bit immediate data from op1 over bits 3-1 of code [0] */
bbb(op)
register struct _oprnd *op;
{
if (op->_data & ~7) return ERR_BBB;
code[0] |= (op->_data << 1);
return NULL;
}
/* first ext word holds bit number (7/31) from first operand */
bbbx(size, op)
int size;
struct _oprnd *op;
{
switch (size) {
case 3:
if (op->_data & ~7L) return ERR_BX3; /* range? */
case 5:
if (op->_data & ~31L) return ERR_BX5;
code[3] = op->_data;
return 1; /* 1 ext word */
default:
return ERR_BX;
}
}
/** mask bits 3-1 of first byte with op1, 8 = 00 */
ccc(op)
register struct _oprnd *op;
{
if (op->_data < 1L || op->_data > 8L) return ERR_CCC;
code[0] |= (op->_data << 1) & 0x0f;
/** if (op->_data != 8L) code[0] |= op->_data << 1; **/
return NULL; /* no words added */
}
/* mask bits 3-1 of first byte, or bits 2-0 of second, with op reg */
rsd(byt, op)
int byt;
register struct _oprnd *op;
{
code[byt] |= (byt) ? op->_reg : op->_reg << 1;
return NULL;
}
/* register mask list from op into ext */
mmkk(order, op)
char order;
register struct _oprnd *op;
{
register int x;
unsigned u1 = 0;
unsigned m1 = 0x0001;
unsigned m2 = 0x8000;
switch (order) {
case '>':
code[2] = op->_reg_list >> 8; /* high byte */
code[3] = op->_reg_list; /* low byte */
return 1;
case '<':
for (x = 15; x >= 0; --x) {
u1 |= (op->_reg_list & (m1 << x)) ? (m2 >> x) : 0;
}
code[2] = u1 >> 8; /* high byte */
code[3] = u1; /* low byte */
return 1;
default:
return ERR_MK;
}
}
/* combined e, f, g, h, and j routines, 12/4/82 */
efghj(arg, i, op)
register char arg;
register int i;
register struct _oprnd *op;
{
int len, displ;
switch (op->_typ) {
case _ani: /* (an) */
if (arg == 'g') {
code[0] |= (op->_reg << 1);
code[1] |= 0x80;
}
else {
code[1] |= (0x10 | op->_reg);
}
return NULL;
case _pd_ani: /* -(an) */
switch (arg) {
case 'g':
code[0] |= (0x01 | op->_reg << 1);
return NULL;
case 'j': return ERR_J;
case 'h': return ERR_H;
default:
code[1] |= (0x20 | op->_reg);
return NULL;
}
case _ani_pi: /* (an)+ */
switch (arg) {
case 'g':
code[0] |= (op->_reg << 1);
code[1] |= 0xc0;
return NULL;
case 'j': return ERR_J;
case 'h': return ERR_H;
default:
code[1] |= (0x18 | op->_reg);
return NULL;
}
case _d16_ani: /* d16(an) */
switch (arg) {
case 'e':
case 'j':
if (/**rorg**/ op->_rel_lbl) {
op->_ireg = op->_reg; /* reg is an index */
op->_iregtyp = op->_regtyp; /* move type */
op->_displ -= (loc_counter + 2); /* make pc relative */
code[1] |= 0x3b;
return _d8_i(i, op); /* indexed label */
}
break;
case 'g':
code[0] |= (0x01 | op->_reg << 1);
code[1] |= 0x40;
return _d16(i, op);
}
code[1] |= (0x28 | op->_reg);
return _d16(i, op);
case _d8_anx: /* d8(an,i) */
if (arg == 'g') {
code[0] |= (0x01 | op->_reg << 1);
code[1] |= 0x80;
}
else {
code[1] |= (0x30 | op->_reg);
}
return _d8_i(i, op);
case _address: /* abs. add., short or long, or label if _rel_lbl */
switch (arg) {
case 'e':
case 'j':
if (/**rorg**/ op->_rel_lbl) {
code[1] |= 0x3a;
op->_displ = op->_addr - (loc_counter + 2); /* rel. to pc */
return _d16(i, op); /* finish as 'label' */
}
break;
case 'g':
code[1] |= 0xc0;
if (op->_long_val) {
code[0] |= 0x03;
code[i++] = op->_addr >> 24;
code[i++] = op->_addr >> 16;
len = 2;
}
else {
code[0] |= (0x01);
len = 1;
}
code[i++] = op->_addr >> 8;
code[i] = op->_addr;
return len;
}
if (op->_long_val) {
code[1] |= (0x39);
code[i++] = op->_addr >> 24;
code[i++] = op->_addr >> 16;
len = 2;
}
else {
code[1] |= (0x38);
len = 1;
}
code[i++] = op->_addr >> 8;
code[i] = op->_addr;
return len;
case _label: /* relative label */
switch (arg) {
case 'g': return ERR_G;
case 'f': return ERR_F;
case 'h': return ERR_H;
default:
code[1] |= 0x3a;
op->_displ -= (loc_counter + 2); /* rel. to pc */
return _d16(i, op);
}
case _labeli: /* label(i) */
switch (arg) {
case 'g': return ERR_G;
case 'f': return ERR_F;
case 'h': return ERR_H;
default:
code[1] |= 0x3b;
op->_displ -= (loc_counter + 2); /* rel. to pc */
return _d8_i(i, op);
}
default:
return ERR_EFGHJ;
}
}
_d16(i, op)
register int i;
register struct _oprnd *op;
{
if ((op->_displ > 32767) || (op->_displ < -32768)) return ERR_D16;
code[i] = op->_displ >> 8; /* displacement... */
code[i+1] = op->_displ; /* ...into ext */
return 1; /* 1 ext word returned */
}
_d8_i(i, op)
register int i;
register struct _oprnd *op;
{
if ((op->_displ > 127) || (op->_displ < -128)) return ERR_D8I;
if (op->_iregtyp == 'a') code[i] |= 0x80; /* index is addr reg */
code[i] |= (op->_ireg << 4); /* add index reg # */
if (op->_inxl) code[i] |= 0x08; /* mark long index size */
code[i+1] = op->_dis